package com.mark.springsecurity.controller;

import com.mark.springsecurity.dto.resp.MessageType;
import com.mark.springsecurity.dto.resp.Msg;
import com.mark.springsecurity.exception.CustomException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ValidationException;
import java.util.stream.Collectors;

/**
 * 全局异常处理
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 运行时异常处理
     *
     * @param e 运行时异常
     * @return 错误信息
     */
    @ExceptionHandler(value = RuntimeException.class)
    public ResponseEntity<Object> handle(RuntimeException e) {
        log.error("全局异常处理 e", e);
        Msg<Object> msg = new Msg<>(MessageType.MSG_TYPE_FAILURE, e.getMessage(), null);
        return new ResponseEntity<>(msg, HttpStatus.INTERNAL_SERVER_ERROR);
    }

    /**
     * 处理请求参数格式错误
     * <p>属性@RequestParam上validate失败后抛出的是{@link javax.validation.ValidationException}
     *
     * @param e 校验异常
     * @return 错误信息
     */
    @ExceptionHandler(ValidationException.class)
    public ResponseEntity<Msg<Object>> validationExceptionHandler(ValidationException e) {
        Msg<Object> msg = new Msg<>(MessageType.MSG_TYPE_FAILURE, e.getMessage(), null);
        return new ResponseEntity<>(msg, HttpStatus.BAD_REQUEST);
    }

    /**
     * 处理请求参数格式错误
     * <p>对象@RequestBody上validate失败后抛出的是{@link org.springframework.web.bind.MethodArgumentNotValidException}<br/>
     * 对象@RequestParam上validate失败后抛出的是{@link org.springframework.validation.BindException}
     *
     * @param e 绑定异常
     * @return 错误信息
     */
    @ExceptionHandler(BindException.class)
    public ResponseEntity<Msg<Object>> bindExceptionHandler(BindException e) {
        String message = e.getFieldErrors()
                .stream()
                .map(fieldError -> fieldError.getField() + fieldError.getDefaultMessage())
                .collect(Collectors.joining(", "));
        Msg<Object> msg = new Msg<>(MessageType.MSG_TYPE_FAILURE, message, null);
        return new ResponseEntity<>(msg, HttpStatus.BAD_REQUEST);
    }

    /**
     * 处理自定义异常
     *
     * @param e 自定义异常
     * @return 错误信息
     */
    @ExceptionHandler(CustomException.class)
    public ResponseEntity<Msg<Object>> customerExceptionHandler(CustomException e) {
        Msg<Object> msg = new Msg<>(MessageType.MSG_TYPE_FAILURE, e.getMessage(), null);
        return new ResponseEntity<>(msg, e.getStatus());
    }
}
